package com.ruoyi.electronicFence.task;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.common.config.DbInterfaceConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.electronicFence.constant.WebSocketConstant;
import com.ruoyi.electronicFence.domain.vo.ReqVo;
import com.ruoyi.electronicFence.utils.HttpUtil;
import com.ruoyi.electronicFence.domain.*;
import com.ruoyi.electronicFence.domain.vo.WebSocketVo;
import com.ruoyi.electronicFence.service.*;
import com.ruoyi.electronicFence.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.StringReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author wsl
 * @Date 2025-02-13 9:31
 * @Version 1.0
 */

@Configuration
@EnableScheduling
@Slf4j
public class RegularlyModifyEnableStatusTasks  implements SchedulingConfigurer {

    @Autowired
    private ElectronicFenceService electronicFenceService;

    @Autowired
    private RecordReadingLocationService recordReadingLocationService;

//    @Autowired
//    private rddqwzService rddqwzService;
//
//    @Autowired
//    private wldqwzService wldqwzService;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private A2ROfEFIntrusionService a2ROfEFIntrusionService;

    @Autowired
    private DynamicsInfoService dynamicsInfoService;

    @Autowired
    private StaticInfoService staticInfoService;


    @Autowired
    private WebSocketServer webSocketServer;

    private static final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap(1024);

    private static final String ADS = "ADS-";

    private static final String AIS = "AIS-";

    private static ConcurrentHashSet<ElectronicFence> hashSet = new ConcurrentHashSet();

    @Autowired
    private DbInterfaceConfig dbInterfaceConfig;






    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                () -> this.execute(),
                triggerContext -> {
                    //每日零点执行
                    String cron = "0 0 0 * * ?";
//                    String cron = "0/5 * * * * ?";
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );
//
//        taskRegistrar.addTriggerTask(
//                () -> this.selectDynamicInfo(),
//                triggerContext -> {
//                    //每日零点执行
//                    String cron = "0/5 * * * * ?";
//                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
//                }
//        );
    }

    /**
     * @description:  根据电子围栏的结束时间   自动更改电子围栏的状态   判断已结束时间在当前时间之前 修改为禁止
     * @author: wsl
     * @date: 2025-02-13 13:30
     **/
    public void execute() {
//        QueryWrapper<ElectronicFence> wrapper = new QueryWrapper<>();
//        wrapper.select("rwid", "qyzt", "jssj");
//        wrapper.eq("qyzt", 1);
//        List<ElectronicFence> list = electronicFenceService.list(wrapper);

        StringBuilder sb = new StringBuilder("select id, qyzt, jssj from J_KY_R_DZWLLB where qyzt = 1");
        List<ElectronicFence> list = (List<ElectronicFence>) HttpUtil.getListBean(dbInterfaceConfig, new ReqVo(sb.toString()), ElectronicFence.class);
        Date now = new Date();
        list.parallelStream().forEach(electronicFence -> {
            if(electronicFence.getJssj().before(now)){
                electronicFenceService.updateqyztById(electronicFence.getId(), 2);
            }
        });
    }

    public void selectDynamicInfo(){

        System.out.println("---------------------------------------------------------------------------------");
        RecordReadingLocation localtion = recordReadingLocationService.getOneBySql();
        //数据库为空时 补全数据
        if(localtion == null){
            localtion = new RecordReadingLocation();
            localtion.setId(1L);
            localtion.setRddqwz(DateUtils.getTime());
            localtion.setWldqwz(DateUtils.getTime());
        }
        //获取当前最大数据的id
        String adsMaxId = dynamicsInfoService.selectMaxId();
        // 查询出需要判断的数据
//        QueryWrapper<DynamicsInfo> a2DynamicsInfoQueryWrapper = new QueryWrapper<>();
//        a2DynamicsInfoQueryWrapper.select("id", "mmsi_icao", "base_time", "lon", "lat");
//        a2DynamicsInfoQueryWrapper.between("id", localtion.getRddqwz(), adsMaxId);
        List<DynamicsInfo> adsList = dynamicsInfoService.getList(LocalDateTime.parse(localtion.getWldqwz(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), adsMaxId);

//        threadPoolTaskExecutor.execute(() -> {
//            adsList.forEach(dynamicsInfo -> {
//                webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo(WebSocketConstant.REAL_TIME_TRAJECTORY,dynamicsInfo)));
//            });
//        });
        //查询出来的id   根据静态数据库id  将一个飞机的航线分组出来
//        Map<Long, List<rddqwz>> adsMap = adsList.stream().collect(Collectors.groupingBy(rddqwz::getAdsbStaticDataId));

        Map<String, List<DynamicsInfo>> adsMap = adsList.stream()
                .collect(Collectors.groupingBy(
                        DynamicsInfo::getMbbm,
                        Collectors.mapping(
                                Function.identity(),
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        list -> {
                                            list.sort(Comparator.comparing(DynamicsInfo::getJjsj));
                                            return list;
                                        }
                                )
                        )
                ));

        //把每条航线得点交给线程池去执行
        adsMap.forEach((k, v) -> {
            threadPoolTaskExecutor.execute(() ->{
                //1. 判断点位的状态  在几个区域内
                for (DynamicsInfo rddqwz : v) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }


                    rddqwz.setLon(rddqwz.getJd() / 1000000.0);
                    rddqwz.setLat(rddqwz.getWd() / 1000000.0);
                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo(WebSocketConstant.REAL_TIME_TRAJECTORY,rddqwz)));
                    Set<String> keySet = map.keySet().stream().filter(key -> key.startsWith(ADS + rddqwz.getMbbm())).collect(Collectors.toSet());
                    //判断是否在区域内
//                    List<ElectronicFence> breakOrOut = electronicFenceService.isBreakOrOut(rddqwz.getJd(), rddqwz.getWd(), rddqwz.getJjsj());
                    List<ElectronicFence> breakOrOut = isBreakOrOut(rddqwz.getJd(), rddqwz.getWd(), rddqwz.getJjsj());

                    if(CollectionUtils.isNotEmpty(breakOrOut)){
                        //2. 根据上一个点的状态，判断是不是闯入闯出 然后插入记录数据 更新闯入闯出状态
                        Set<String> cacheSet = new HashSet<>();
                        for (ElectronicFence electronicFence : breakOrOut) {
                            String key = ADS + rddqwz.getMbbm() + "-" + electronicFence.getId();
                            if(map.get(key) == null ||  map.get(key) != 1){
                                //todo 电子围栏闯入
                                A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                                a2ROfEFIntrusion.setRwwibh(electronicFence.getId());
                                a2ROfEFIntrusion.setDwwybh(rddqwz.getId());
                                a2ROfEFIntrusion.setZt(1);
                                a2ROfEFIntrusionService.saveOne(a2ROfEFIntrusion);

                                A2StaticInfo a2StaticInfo = staticInfoService.selectByMmsiIcao(rddqwz.getMbbm());
                                HashMap<String, Object> websocketMap = new HashMap<>();
                                websocketMap.put("name", a2StaticInfo.getMbmc());
                                websocketMap.put("lon", rddqwz.getJd() / 1000000.0);
                                websocketMap.put("lat", rddqwz.getWd() / 1000000.0);
                                websocketMap.put("mmsiIcao", rddqwz.getMbbm());
                                websocketMap.put("jczt", 1);
                                webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                                map.put(key, 1);
                            }
                            cacheSet.add(key);
                        }
                        //3. 查询之前存在但是现在不在的区域  修改为闯出
                        keySet.removeAll(cacheSet);

                        if(CollectionUtils.isNotEmpty(keySet)){
                            //todo 闯出
                            keySet.forEach(key ->{
                                if(map.get(key) != null  && map.get(key) == 1){
                                    A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                                    String rwid = key.substring(key.lastIndexOf("-") + 1, key.length());
                                    a2ROfEFIntrusion.setRwwibh(Long.valueOf(rwid));
                                    a2ROfEFIntrusion.setDwwybh(rddqwz.getId());
                                    a2ROfEFIntrusion.setZt(2);
                                    a2ROfEFIntrusionService.saveOne(a2ROfEFIntrusion);
                                    map.put(key, 2);
                                    A2StaticInfo a2StaticInfo = staticInfoService.selectByMmsiIcao(rddqwz.getMbbm());
                                    HashMap<String, Object> websocketMap = new HashMap<>();
                                    websocketMap.put("name", a2StaticInfo.getMbmc());
                                    websocketMap.put("lon", rddqwz.getJd() / 1000000.0);
                                    websocketMap.put("lat", rddqwz.getWd() / 1000000.0);
                                    websocketMap.put("mmsiIcao", rddqwz.getMbbm());
                                    websocketMap.put("jczt", 2);

                                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                                }
                            });
                        }
                    } else {
                        //3. 查询之前存在但是现在不在的区域  修改为闯出
                        if(CollectionUtils.isNotEmpty(keySet)){
                            keySet.forEach(key -> {
                                //闯出
                                if(map.get(key) != null  && map.get(key) == 1){
                                    A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
                                    String rwid = key.substring(key.lastIndexOf("-") + 1, key.length());
                                    a2ROfEFIntrusion.setRwwibh(Long.valueOf(rwid));
                                    a2ROfEFIntrusion.setDwwybh(rddqwz.getId());
                                    a2ROfEFIntrusion.setZt(2);
                                    a2ROfEFIntrusionService.saveOne(a2ROfEFIntrusion);

                                    A2StaticInfo a2StaticInfo = staticInfoService.selectByMmsiIcao(rddqwz.getMbbm());
                                    HashMap<String, Object> websocketMap = new HashMap<>();
                                    websocketMap.put("name", a2StaticInfo.getMbmc());
                                    websocketMap.put("lon", rddqwz.getJd() / 1000000.0);
                                    websocketMap.put("lat", rddqwz.getWd() / 1000000.0);
                                    websocketMap.put("mmsiIcao", rddqwz.getMbbm());
                                    websocketMap.put("jczt", 2);

                                    webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo("ELE", websocketMap)));
                                    map.put(key, 2);
                                }
                            });
                        }
                    }
                }
            });
        });

//        threadPoolTaskExecutor.execute(() -> {
//            adsList.forEach(dynamicsInfo -> {
//                webSocketServer.sendInfo(JSON.toJSONString(new WebSocketVo(WebSocketConstant.REAL_TIME_TRAJECTORY,dynamicsInfo)));
//            });
//        });

//        QueryWrapper<wldqwz> wldqwzQueryWrapper = new QueryWrapper<>();
//        wldqwzQueryWrapper.select("id", "ais_static_data_id","basis_time", "center_lon", "center_lat");
//        wldqwzQueryWrapper.between("id", localtion.getwldqwz(), aisMaxId);
//        List<wldqwz> aisList = wldqwzService.list(wldqwzQueryWrapper);
//        Map<Long, List<wldqwz>> aisMap = aisList.stream().collect(Collectors.groupingBy(wldqwz::getAisStaticDataId));

//        aisMap.forEach((k, v) -> {
//            threadPoolTaskExecutor.execute(() ->{
//                for (wldqwz wldqwz : v) {
//                    Set<String> keySet = map.keySet().stream().filter(key -> key.startsWith(AIS + wldqwz.getAisStaticDataId())).collect(Collectors.toSet());
//                    //判断是否在区域内
//                    List<ElectronicFence> breakOrOut = electronicFenceService.isBreakOrOut(wldqwz.getCenterLon(), wldqwz.getCenterLat(), wldqwz.getBasisTime());
//                    if(CollectionUtils.isNotEmpty(breakOrOut)){
//                        Set<String> cacheSet = new HashSet<>();
//                        for (ElectronicFence electronicFence : breakOrOut) {
//                            String key = ADS + wldqwz.getAisStaticDataId() + "-" + electronicFence.getRwid();
//                            if(map.get(key) != 1){
//                                //todo 电子围栏闯入
//                                A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
//                                a2ROfEFIntrusion.setRwid(electronicFence.getRwid());
//                                a2ROfEFIntrusion.setDwid(wldqwz.getId());
//                                a2ROfEFIntrusion.setJczt(1);
//                                a2ROfEFIntrusion.setlx(2);
//                                a2ROfEFIntrusionService.save(a2ROfEFIntrusion);
//                                map.put(key, 1);
//                            }
//                            cacheSet.add(key);
//                        }
//                        keySet.removeAll(cacheSet);
//
//                        if(CollectionUtils.isNotEmpty(keySet)){
//                            //todo 闯出
//                            keySet.forEach(key ->{
//                                if(map.get(key) == 1){
//                                    A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
//                                    String rwid = key.substring(key.lastIndexOf("-"), key.length());
//                                    a2ROfEFIntrusion.setRwid(Long.valueOf(rwid));
//                                    a2ROfEFIntrusion.setDwid(wldqwz.getId());
//                                    a2ROfEFIntrusion.setJczt(2);
//                                    a2ROfEFIntrusion.setlx(2);
//                                    a2ROfEFIntrusionService.save(a2ROfEFIntrusion);
//                                    map.put(key, 2);
//                                }
//                            });
//                        }
//                    } else {
//                        if(CollectionUtils.isNotEmpty(keySet)){
//                            keySet.forEach(key -> {
//                                //闯出
//                                if(map.get(key) == 1){
//                                    A2ROfEFIntrusion a2ROfEFIntrusion = new A2ROfEFIntrusion();
//                                    String rwid = key.substring(key.lastIndexOf("-"), key.length());
//                                    a2ROfEFIntrusion.setRwid(Long.valueOf(rwid));
//                                    a2ROfEFIntrusion.setDwid(wldqwz.getId());
//                                    a2ROfEFIntrusion.setJczt(2);
//                                    a2ROfEFIntrusion.setlx(2);
//                                    a2ROfEFIntrusionService.save(a2ROfEFIntrusion);
//                                    map.put(key, 2);
//                                }
//                            });
//                        }
//                    }
//                }
//            });
//        });

//        UpdateWrapper<RecordReadingLocation> wrap = new UpdateWrapper<>();
//        wrap.eq("id", localtion.getId());
//        wrap.set("adsb_dynamic_info", adsMaxId + 1);
//        recordReadingLocationService.update(wrap);
        StringBuilder sb = new StringBuilder("UPDATE J_KY_S_DWDQJL  SET wldqwz='").append(adsMaxId).append("' where id = ").append(localtion.getId());
        HttpUtil.create(dbInterfaceConfig, new ReqVo(sb.toString()));
    }

//    @PostConstruct
    public void initEleSet() throws IOException {
        StringBuilder sb = new StringBuilder("");
        sb.append("SELECT e.id, e.glid, e.qyzt, e.kssj, e.jssj, e.sjcrsj, r.qymc, r.qyjson FROM J_KY_R_DZWLLB e LEFT JOIN J_KY_S_QYXXB r ON e.glid = r.id");
        List<ElectronicFence> listBean = (List<ElectronicFence>) HttpUtil.getListBean(dbInterfaceConfig, new ReqVo(sb.toString()), ElectronicFence.class);
        for (ElectronicFence electronicFence : listBean) {
            GeometryJSON geometryJSON = new GeometryJSON();
            Geometry ge = geometryJSON.read(new StringReader(electronicFence.getQyjson()));
            electronicFence.setGe(ge);
        }
        hashSet.addAll(listBean);
    }

    public List<ElectronicFence> isBreakOrOut(Long lon, Long lat, Date baseTime){
        double lon1 = (double) lon / 1000000.0;
        double lat1 = lat / 1000000.0;
        List<ElectronicFence> returnList = new ArrayList<>();
        hashSet.forEach(ele -> {
            Point point = null;
            try {
                GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
                point = geometryFactory.createPoint(new Coordinate(lon1, lat1));
                if (ele.getQyzt() == 1 && ele.getGe().contains(point) && (ele.getKssj() == null || baseTime.after(ele.getKssj())) && (ele.getJssj() == null || baseTime.before(ele.getJssj()))) {
                    returnList.add(ele);
                }
            } catch (Exception e) {
                log.error("比较失败", e);
            }
        });
        return returnList;
    }


}
